package gofish.json;

import gofish.objects.Game;
import gofish.objects.GameData;
import gofish.objects.Player;

import java.util.ArrayList;

/**
 * JsonObject is a composite node in the AbstractJson family.
 * It holds an ArrayList (inherited from AbstractCompositeJson)
 * of AbstractJson elements, which for this class will all be
 * of type JsonObjectElement.
 * This inherits toString() from AbstractCompositeJson, which
 * will return "{" + toString() called on every element in the
 * ArrayList + "}".
 * @author Matt Lauber
 *
 */
 // NOTE: MAY HAVE TO CHANGE TURN TO BE string playerName.
 //   ALSO MAY NEED KYLYN TO MAKE A FUNCTION TO GET THIS INFO.
public class JsonObject extends AbstractCompositeJson {
	
	/**
	 * This class has multiple constructors that all assign
	 * as their startSymbol and endSymbol (inherited) the symbols
	 * "{" and "}", as per JSON format.
	 * The no argument constructor only assigns those symbols. All
	 * other constructors do that and then add to their ArrayList whatever
	 * object you pass in as an argument, along with the key that you
	 * also pass in.  This way when you create a JsonObject, you can
	 * pre-populate it with a key-value pair by using the constructor.
	 * The values that can be passed to the constructor include String,
	 * an array of JsonObjectElement(s), an AbstractCompositeJson (which would
	 * either be a JsonObject or a JsonArray), a char, int, double, and boolean.
	 */
	public JsonObject() {
		super("{", "}");
	}
	
	public JsonObject(JsonObjectElement... elms) {
		super("{", "}");
		add(elms);
	}
	
	public JsonObject(String key, AbstractCompositeJson value) {
		super("{", "}");
		add(key, value);
	}
	
	public JsonObject(String key, String value) {
		super("{", "}");
		add(key, value);
	}
	
	public JsonObject(String key, char value) {
		super("{", "}");
		add(key, value);
	}
	
	public JsonObject(String key, int value) {
		super("{", "}");
		add(key, value);
	}
	
	public JsonObject(String key, double value) {
		super("{", "}");
		add(key, value);
	}
	
	public JsonObject(String key, boolean value) {
		super("{", "}");
		add(key, value);
	}
	
	public JsonObject(Game game, String currentUser) {
		super("{", "}");
		add("player", new JsonObject(game.getPlayer(currentUser)));
		JsonArray opponents = new JsonArray();
		ArrayList<Player> g = game.getPlayerMap();
		
		for (Player p : g) {
			//System.out.println(p.getPairs());
			if (!p.getUserName().equals(currentUser)) {
				opponents.add(p);
			}
		}
		add("opponents", opponents);
		
		add("turn", game.getTurn());
		
		if (GameData.getEventId(game.getGid()) == -1) {
			JsonArray winners = new JsonArray();
			int mostPairs = -1;
			int temp;
			for (Player p : game.getPlayerMap()) {
				temp = p.getPairs().length();
				if (temp > mostPairs) {
					mostPairs = temp;
				}
			}
			for (Player p : game.getPlayerMap()) {
				if (p.getPairs().length() == mostPairs) {
					winners.add(p.getUserName());
				}
			}
			add("winners", winners);
		}
	}
	
	public JsonObject(Player player) {
		super("{", "}");
		
		// may change if hand is an array instead of a String
		// may need try-catch in for-loop
		JsonArray responseHand = new JsonArray();
		String playersHand = player.getHand(); 
		for (int i = 0; i < playersHand.length(); i += 2) {
			responseHand.add(playersHand.substring(i, i + 2));
		}
		add("hand", responseHand);
		
		// may change if pairs is an array instead of a String
		// may need try-catch in for-loop
		JsonArray responsePairs = new JsonArray();
		String playersPairs = player.getPairs();
		for (int i = 0; i < playersPairs.length(); ++i) {
			responsePairs.add( String.valueOf(playersPairs.charAt(i)) );
		}
		add("pairs", responsePairs);
	}
	
	/**
	 * The add() method adds whatever you pass in as an argument to this
	 * object's ArrayList, so that when you call toString(), it will be
	 * printed.  The add() method is overloaded so that it can accept
	 * the same arguments as the constructors.  If you use the addNull()
	 * method, which accepts a key without a value to go with it, it will
	 * set the value to a String representation of null. 
	 * @param value : the object to be added to the ArrayList
	 * @return : a reference to this object, so that add() calls can be strung together, as add(x).add(y).add(z) etc
	 */
	public JsonObject add(JsonObjectElement... elms) {
		for (JsonObjectElement e : elms) {
			elements.add(e);
		}
		return this;
	}
	
	public JsonObject add(String key, AbstractCompositeJson value) {
		elements.add(new JsonObjectElement(key, value));
		return this;
	}
	
	public JsonObject add(String key, String element) {
		elements.add( new JsonObjectElement(key, element) );
		return this;
	}
	
	public JsonObject add(String key, char element) {
		elements.add( new JsonObjectElement(key, element) );
		return this;
	}
	
	public JsonObject add(String key, int element) {
		elements.add( new JsonObjectElement(key, element) );
		return this;
	}
	
	public JsonObject add(String key, double element) {
		elements.add( new JsonObjectElement(key, element) );
		return this;
	}
	
	public JsonObject add(String key, boolean element) {
		elements.add( new JsonObjectElement(key, element) );
		return this;
	}
	
	public JsonObject addNull(String key) {
		elements.add(new JsonObjectElement(key));
		return this;
	}
}
